home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 1.0 beta / flock-1.0RC3.en-US.win32.exe / flock / components / flockAccountUtils.js < prev    next >
Text File  |  2007-10-18  |  32KB  |  910 lines

  1. // vim: ts=2 sw=2 expandtab cindent
  2. //
  3. // BEGIN FLOCK GPL
  4. // 
  5. // Copyright Flock Inc. 2005-2007
  6. // http://flock.com
  7. // 
  8. // This file may be used under the terms of of the
  9. // GNU General Public License Version 2 or later (the "GPL"),
  10. // http://www.gnu.org/licenses/gpl.html
  11. // 
  12. // Software distributed under the License is distributed on an "AS IS" basis,
  13. // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. // for the specific language governing rights and limitations under the
  15. // License.
  16. // 
  17. // END FLOCK GPL
  18.  
  19. const ACCOUNTUTILS_CID        = Components.ID("{d84bce30-4ce5-11db-b0de-0800200c9a66}");
  20. const ACCOUNTUTILS_CONTRACTID = "@flock.com/account-utils;1";
  21.  
  22. const OBS = Components.classes["@mozilla.org/observer-service;1"]
  23.                       .getService(Components.interfaces.nsIObserverService);
  24.  
  25. // ===================================================
  26. // ========== BEGIN flockAccountUtils class ==========
  27. // ===================================================
  28.  
  29. const ACCOUNTUTILS_INTERFACES = [
  30.   Components.interfaces.nsISupports,
  31.   Components.interfaces.nsIObserver,
  32.   Components.interfaces.flockIAccountUtils,
  33. ];
  34.  
  35. function flockAccountUtils() {
  36.   this._logger = Components.classes['@flock.com/logger;1'].createInstance(Components.interfaces.flockILogger);
  37.   this._logger.init('flockAccountUtils');
  38.   this._logger.info('Created Account Utility Object');
  39.  
  40.   this.mSetupHasRun = false;
  41.   OBS.addObserver(this, "flock-data-ready", false);
  42.  
  43.   // mTempPasswords is an associative array of temporary passwords
  44.   this.mTempPasswords = [];
  45. }
  46.  
  47.  
  48. // BEGIN nsISupports interface
  49. flockAccountUtils.prototype.QueryInterface =
  50. function flockAccountUtils_QueryInterface(aIID)
  51. {
  52.   var interfaces = ACCOUNTUTILS_INTERFACES;
  53.   for (var i in interfaces) {
  54.     if (aIID.equals(interfaces[i])) {
  55.       return this;
  56.     }
  57.   }
  58.   throw Components.results.NS_ERROR_NO_INTERFACE;
  59. }
  60. // END nsISupports interface
  61.  
  62.  
  63. // BEGIN nsIObserver interface
  64. flockAccountUtils.prototype.observe =
  65. function flockAccountUtils_observe(aSubject, aTopic, aState)
  66. {
  67.   switch (aTopic) {
  68.     case 'flock-data-ready':
  69.       OBS.removeObserver(this, "flock-data-ready");
  70.       this.setup();
  71.       break;
  72.   }
  73. }
  74. // END nsIObserver interface
  75.  
  76.  
  77. // BEGIN flockIAccountUtils interface
  78. flockAccountUtils.prototype.activatedAccountExists =
  79. function flockAccountUtils_activatedAccountExists(aServiceURN)
  80. {
  81.   this._logger.info("{flockIAccountUtils}.activatedAccountExists('"+aServiceURN+"')");
  82.   this.setup();
  83.   var svc = this._coop.get(aServiceURN);
  84.   if (!svc) {
  85.     throw Components.results.NS_ERROR_UNEXPECTED;
  86.   }
  87.   var accounts = this._coop.Account.find({service: svc, isTransient: false});
  88.   return (accounts.length > 0);
  89. }
  90.  
  91. flockAccountUtils.prototype.clearTempPassword =
  92. function flockAccountUtils_clearTempPassword(aKey)
  93. {
  94.   this._logger.info("{flockIAccountUtils}.clearTempPassword('"+aKey+"')");
  95.   this.mTempPasswords[aKey] = undefined;
  96. }
  97.  
  98. flockAccountUtils.prototype.ensureOnlyAuthenticatedAccount =
  99. function flockAccountUtils_ensureOnlyAuthenticatedAccount(aAccountURN)
  100. {
  101.   this._logger.info("{flockIAccountUtils}.ensureOnlyAuthenticatedAccount('"+aAccountURN+"')");
  102.   this.setup();
  103.   var acctCoopObj = this._coop.get(aAccountURN);
  104.   if (acctCoopObj) {
  105.     var accounts = this._coop.Account.find({serviceId: acctCoopObj.serviceId});
  106.     for (var i = 0; i < accounts.length; i++) {
  107.       // Here I'm trying not to change the RDF unless I actually need to, in
  108.       // order to avoid RDF change notifications from being fired
  109.       // unnecessarily
  110.       if (accounts[i].id() == aAccountURN) {
  111.         if (!accounts[i].isAuthenticated) {
  112.           accounts[i].isAuthenticated = true;
  113.         }
  114.       } else {
  115.         if (accounts[i].isAuthenticated) {
  116.           accounts[i].isAuthenticated = false;
  117.         }
  118.       }
  119.     }
  120.   }
  121. }
  122.  
  123. flockAccountUtils.prototype.getAccountURNById =
  124. function flockAccountUtils_getAccountURNById(aServiceURN, aAccountID)
  125. {
  126.   this._logger.info("{flockIAccountUtils}.getAccountURNById('"+aServiceURN+"', '"+aAccountID+"')");
  127.   this.setup();
  128.   var svc = this._coop.get(aServiceURN);
  129.   if (!svc) {
  130.     throw Components.results.NS_ERROR_UNEXPECTED;
  131.   }
  132.   var accounts = this._coop.Account.find({service: svc, accountId: aAccountID});
  133.   this._logger.info(" - found "+accounts.length+" matching account (should be exactly 1)");
  134.   if (accounts.length > 0) {
  135.     this._logger.info(" - account urn = "+accounts[0].id());
  136.     return accounts[0].id();
  137.   }
  138.   return null;
  139. }
  140.  
  141. flockAccountUtils.prototype.getAccountURNByLogin =
  142. function flockAccountUtils_getAccountURNByLogin(aServiceURN, aLogin)
  143. {
  144.   this._logger.info("{flockIAccountUtils}.getAccountURNByLogin('"+aServiceURN+"', '"+aLogin+"')");
  145.   var pm = Components.classes["@mozilla.org/passwordmanager;1"]
  146.                      .getService(Components.interfaces.nsIPasswordManager);
  147.   var en = pm.enumerator;
  148.   while (en.hasMoreElements()) {
  149.     var p = en.getNext();
  150.     p.QueryInterface(Components.interfaces.nsIPassword);
  151.     if (p.user == aLogin && (p.host.indexOf(aServiceURN)==0)) {
  152.       var accountID = p.host.substring(aServiceURN.length+1);
  153.       return this.getAccountURNById(aServiceURN, accountID);
  154.     }
  155.   }
  156.   return null;
  157. }
  158.  
  159. flockAccountUtils.prototype.getAccountsForService =
  160. function flockAccountUtils_getAccountsForService(aServiceContractID)
  161. {
  162.   this._logger.info("{flockIAccountUtils}.getAccountsForService('"+aServiceContractID+"')");
  163.   this.setup();
  164.   var accountsEnum = {
  165.     arr : [],
  166.     QueryInterface : function(iid) {
  167.       if (!iid.equals(Components.interfaces.nsISupports) &&
  168.           !iid.equals(Components.interfaces.nsISimpleEnumerator))
  169.       {
  170.         throw Components.results.NS_ERROR_NO_INTERFACE;
  171.       }
  172.       return this;
  173.     },
  174.     hasMoreElements : function() {
  175.       return (this.arr.length > 0);
  176.     },
  177.     getNext : function() {
  178.       return this.arr.pop();
  179.     }
  180.   };
  181.   var accounts = this._coop.Account.find({serviceId: aServiceContractID});
  182.   var svc = Components.classes[aServiceContractID]
  183.                       .getService(Components.interfaces.flockIWebService);
  184.   for (var i = accounts.length - 1; i >= 0; i--) {
  185.     accountsEnum.arr.push(svc.getAccount(accounts[i].id()));
  186.   }
  187.   return accountsEnum;
  188. }
  189.  
  190. flockAccountUtils.prototype.getWebServicesByInterface =
  191. function flockAccountUtils_getWebServicesByInterface(aWebServiceInterface)
  192. {
  193.   var servicesEnum = {
  194.     _arr: [],
  195.     QueryInterface: function se_QueryInterface(aIid) {
  196.       if (aIid.equals(Components.interfaces.nsISupports) ||
  197.           aIid.equals(Components.interfaces.nsISimpleEnumerator))
  198.       {
  199.         return this;
  200.       }
  201.       throw Components.results.NS_ERROR_NO_INTERFACE;
  202.     },
  203.     hasMoreElements: function se_hasMoreElements() {
  204.       return (this._arr.length > 0);
  205.     },
  206.     getNext: function se_getNext() {
  207.       return this._arr.pop();
  208.     }
  209.   };
  210.  
  211.   var catMgr = Components.classes["@mozilla.org/categorymanager;1"]
  212.                          .getService(Components.interfaces.nsICategoryManager);
  213.   var catsEnum = catMgr.enumerateCategory("flockWebService");
  214.   while (catsEnum.hasMoreElements()) {
  215.     var entry = catsEnum.getNext()
  216.                         .QueryInterface(Components.interfaces.nsISupportsCString);
  217.     var contractId = catMgr.getCategoryEntry("flockWebService", entry.data);
  218.     var svc = Components.classes[contractId]
  219.                         .getService(Components.interfaces.flockIWebService);
  220.     if (svc instanceof Components.interfaces[aWebServiceInterface]) {
  221.       servicesEnum._arr.push(svc);
  222.     }
  223.   }
  224.  
  225.   return servicesEnum;
  226. }
  227.  
  228. flockAccountUtils.prototype.getAccountsByInterface =
  229. function flockAccountUtils_getAccountsByInterface(aServiceInterface)
  230. {
  231.   var accountsEnum = {
  232.     arr : [],
  233.     QueryInterface : function(iid) {
  234.       if (!iid.equals(Components.interfaces.nsISupports) &&
  235.           !iid.equals(Components.interfaces.nsISimpleEnumerator))
  236.       {
  237.         throw Components.results.NS_ERROR_NO_INTERFACE;
  238.       }
  239.       return this;
  240.     },
  241.     hasMoreElements : function() {
  242.       return (this.arr.length > 0);
  243.     },
  244.     getNext : function() {
  245.       return this.arr.pop();
  246.     }
  247.   };
  248.  
  249.   var acctRoot = this._coop.get("http://flock.com/rdf#AccountsRoot");
  250.   var c_accounts = acctRoot.children.enumerate();
  251.   while (c_accounts.hasMoreElements()) {
  252.     var c_account = c_accounts.getNext();
  253.     if (!c_account) continue; // getNext() can return NULL when hasMoreElements() is TRUE.
  254.     if (Components.classes[c_account.serviceId]) {
  255.       var svc = Components.classes[c_account.serviceId]
  256.                           .getService(Components.interfaces.flockIWebService);
  257.       if (svc instanceof Components.interfaces[aServiceInterface]) {
  258.         accountsEnum.arr.push(svc.getAccount(c_account.id()));
  259.       }
  260.     } else {
  261.       this._logger.debug( "No service found for account '"+c_account.name +
  262.                           "' with serviceId: "+c_account.serviceId );
  263.     }
  264.   }
  265.  
  266.   return accountsEnum;
  267. }
  268.  
  269. flockAccountUtils.prototype.doAccountsExist =
  270. function flockAccountUtils_doAccountsExist()
  271. {
  272.   var accounts = this.getAllAccounts();
  273.   if (accounts.hasMoreElements()) {
  274.     return true;
  275.   } else {
  276.     return false;
  277.   }
  278. }
  279.  
  280. flockAccountUtils.prototype.isTransient =
  281. function flockAccountUtils_isTransient(aURN)
  282. {
  283.   return this._coop.get(aURN).isTransient;
  284. }
  285.  
  286. flockAccountUtils.prototype.getElementByAttribute =
  287. function flockAccountUtils_getElementByAttribute(aAncestorElement, aAttributeName, aAttributeValue)
  288. {
  289.   //this._logger.info("{flockIAccountUtils}.getElementByAttribute("+aAncestorElement+", '"+aAttributeName+"', '"+aAttributeValue+"')");
  290.   for (var i = 0; i < aAncestorElement.childNodes.length; i++) {
  291.     var childNode = aAncestorElement.childNodes.item(i);
  292.     try {
  293.       var childElem = childNode.QueryInterface(Components.interfaces.nsIDOMHTMLElement);
  294.       if (childElem.getAttribute(aAttributeName) == aAttributeValue) {
  295.         return childElem;
  296.       }
  297.       var recursiveResult = this.getElementByAttribute(childElem, aAttributeName, aAttributeValue);
  298.       if (recursiveResult) {
  299.         return recursiveResult;
  300.       }
  301.     } catch (ex) {
  302.       // This just means that childNode is not an Element
  303.     }
  304.   }
  305.   return null;
  306. }
  307.  
  308. flockAccountUtils.prototype.getServiceIDForAccountURN =
  309. function flockAccountUtils_getServiceIDForAccountURN(aAccountURN)
  310. {
  311.   var account = this._coop.get(aAccountURN);
  312.   return account.serviceId;
  313. }
  314.  
  315. flockAccountUtils.prototype.createAccount =
  316. function flockAccountUtils_createAccount(aService, aUsername)
  317. {
  318.   aService.QueryInterface(Components.interfaces.nsIClassInfo);
  319.   
  320.   // Add the account
  321.   var accountURN = aService.urn+":"+aUsername;
  322.   var account = new this._coop.Account(accountURN, {
  323.     name: aUsername,
  324.     serviceId: aService.contractId,
  325.     service: null, // FIXME
  326.     accountId: aUsername,
  327.     favicon: aService.icon,
  328.     URL: aService.url,
  329.   });
  330.   this._coop.accounts_root.children.addOnce(account);
  331.   // this.USER = blAccount.id();
  332.   // var acct = this.getAccount(blAccount.id());
  333.  
  334.   // Add the notification stream
  335.   var notificationStream = new this._coop.Stream(accountURN + ":notifications", {
  336.     name: "Notification",
  337.     isPollable: false,
  338.     isIndexable: false,
  339.     notify: true,
  340.     serviceId: aService.contractId
  341.   });
  342.   account.children.addOnce(notificationStream);
  343.   return accountURN;
  344. }
  345.  
  346. flockAccountUtils.prototype.removeAccount =
  347. function flockAccountUtils_removeAccount(aAccountUrn)
  348. {
  349.   this._logger.info("{flockIAccountUtils}.removeAccount('"+aAccountUrn+"')");
  350.   var c_acct = this._coop.get(aAccountUrn);
  351.  
  352.   // Remove associated passwords
  353.   if (c_acct.accountId && c_acct.serviceId && Components.classes[c_acct.serviceId]) {
  354.     var svc = Components.classes[c_acct.serviceId]
  355.                         .getService(Components.interfaces.flockIWebService);
  356.     if (svc) {
  357.       // Clear the internal password entry that some services use
  358.       var internalPWhost = svc.urn+":"+c_acct.accountId;
  359.       this.clearTempPassword(internalPWhost);
  360.       this.removeAllPasswordsForHost(internalPWhost);
  361.       // Clear the user-created password entry for this account, if we can
  362.       // positively identify one
  363.       if (svc instanceof Components.interfaces.flockIManageableWebService) {
  364.         svc.QueryInterface(Components.interfaces.flockIManageableWebService);
  365.         var pm = Components.classes["@mozilla.org/passwordmanager;1"]
  366.                            .getService(Components.interfaces.nsIPasswordManager);
  367.         var en = pm.enumerator;
  368.         var domains = this._coop.get(svc.urn).domains.split(",");
  369.         while (en.hasMoreElements()) {
  370.           var p = en.getNext();
  371.           p.QueryInterface(Components.interfaces.nsIPassword);
  372.           for (var i = 0; i < domains.length; i++) {
  373.             var domain = domains[i];
  374.             var index = p.host.indexOf("."+domain);
  375.             if ( (p.host == "http://"+domain) || (p.host == "https://"+domain) ||
  376.                 ((index != -1) && (index + domain.length + 1 == p.host.length)) )
  377.             {
  378.               // The host for this password matches the service domain
  379.               try {
  380.                 if (p.user == c_acct.username || p.user == c_acct.accountId) {
  381.                   // And the username matches the account, so remove this entry
  382.                   pm.removeUser(p.host, p.user);
  383.                 }
  384.               } catch (ex) {
  385.                 this._logger.debug("ERROR removing password {host: "+p.host+" user: "+c_acct.username+"}");
  386.               }
  387.             }
  388.           }
  389.         }
  390.       }
  391.     }
  392.   }
  393.  
  394.   // Remove all of this Account's children which are Streams or Blogs
  395.   var acctChildren = c_acct.children.enumerate();
  396.   while (acctChildren.hasMoreElements()) {
  397.     var acctChild = acctChildren.getNext();
  398.     if (acctChild.isInstanceOf("http://flock.com/rdf#Stream")) {
  399.       this._logger.info("    removing account Stream");
  400.       var stream = acctChild;
  401.       // Remove all Stream items
  402.       var streamChildren = stream.children.enumerate();
  403.       while (streamChildren.hasMoreElements()) {
  404.         var streamChild = streamChildren.getNext();
  405.         var parents = streamChild.getParents();
  406.         for (var j = 0; j < parents.length; j++) {
  407.           parents[j].children.remove(streamChild);
  408.         }
  409.         streamChild.destroy();
  410.       }
  411.       // Remove Stream from all parents
  412.       var parents = stream.getParents();
  413.       for (var k = 0; k < parents.length; k++) {
  414.         parents[k].children.remove(stream);
  415.       }
  416.       stream.destroy();
  417.     }
  418.     else if (acctChild.isInstanceOf("http://flock.com/rdf#Blog")) {
  419.       this._logger.info("    removing account Blog");
  420.       var parents = acctChild.getParents();
  421.       for (var k = 0; k < parents.length; k++) {
  422.         parents[k].children.remove(acctChild);
  423.       }
  424.       acctChild.destroy();
  425.     }
  426.   }
  427.   
  428.   var friendsList = c_acct.friendsList;
  429.   if (friendsList) {
  430.     if (friendsList.children) {
  431.       var friendsEnum = friendsList.children.enumerate();
  432.       // Remove friends
  433.       while (friendsEnum.hasMoreElements()) {
  434.         var identity = friendsEnum.getNext();
  435.         friendsList.children.remove(identity);
  436.         this._logger.debug("Friend " + identity.accountId
  437.                                      + " has been deleted from RDF");
  438.         identity.destroy();
  439.       }
  440.     }
  441.     // Remove friends list
  442.     friendsList.destroy();
  443.   }
  444.  
  445.   // Remove this Account from all of its parents
  446.   var parents = c_acct.getParents();
  447.   this._logger.info("  account "+aAccountUrn+" has "+parents.length+" parents");
  448.   for (var i = 0; i < parents.length; i++) {
  449.     this._logger.info("   removing from parent "+i);
  450.     parents[i].children.remove(c_acct);
  451.   }
  452.   this._logger.info("  destroying account "+aAccountUrn);
  453.   c_acct.destroy();
  454. }
  455.  
  456. flockAccountUtils.prototype.removeAllAccounts =
  457. function flockAccountUtils_removeAllAccounts()
  458. {
  459.   var c_accounts = this.getAllAccounts();
  460.   while (c_accounts.hasMoreElements()) {
  461.     var c_acct = c_accounts.getNext();
  462.     var svc = Components.classes[c_acct.serviceId]
  463.                         .getService(Components.interfaces.flockIWebService);
  464.     var acct = svc.getAccount(c_acct.id());
  465.     acct.logout(null);
  466.     svc.removeAccount(c_acct.id());
  467.   }
  468. }
  469.  
  470. flockAccountUtils.prototype.getCookie =
  471. function flockAccountUtils_getCookie(aHost, aCookieName)
  472. {
  473.   var ios = Components.classes["@mozilla.org/network/io-service;1"]
  474.                       .getService(Components.interfaces.nsIIOService);
  475.   var cookieSvc = Components.classes["@mozilla.org/cookieService;1"]
  476.                             .getService(Components.interfaces.nsICookieService);
  477.   var uri = ios.newURI(aHost, null, null);
  478.   var cookieString = cookieSvc.getCookieString(uri, null);
  479.   if (!cookieString) { return null; }
  480.   var index = cookieString.indexOf(aCookieName + "=");  
  481.   if (index == -1) { return null; }
  482.   index = cookieString.indexOf("=", index) + 1;  
  483.   var endstr = cookieString.indexOf(";", index);  
  484.   if (endstr == -1) {
  485.     endstr = cookieString.length;  
  486.   }
  487.   var cookieValue = unescape(cookieString.substring(index, endstr));
  488.   this._logger.info("{flockIAccountUtils}.getCookie('"+aHost+"', '"+aCookieName+"'): value = "+cookieValue);
  489.   return cookieValue;
  490. }
  491.  
  492. flockAccountUtils.prototype.getActiveBookmarkAccount =
  493. function flockAccountUtils_getActiveBookmarkAccount()
  494. {
  495.   this._logger.info("{flockIAccountUtils}.getActiveBookmarkAccountURU()");
  496.   var accounts = this._coop.Account.find({isTransient: false, isAuthenticated: true});
  497.   for (var i = 0; i < accounts.length; i++) {
  498.     try {
  499.       var svn = Components.classes[accounts[i].serviceId]
  500.                           .getService(Components.interfaces.flockIBookmarkWebService);
  501.     } catch (ex) {
  502.       continue;
  503.     }
  504.     svn.QueryInterface(Components.interfaces.flockIWebService);
  505.     var account = svn.getAccount(accounts[i].id());
  506.     account.QueryInterface(Components.interfaces.flockIBookmarkWebServiceAccount);
  507.     return account;
  508.   }
  509.   return null;
  510. }
  511.  
  512. flockAccountUtils.prototype.getFirstAuthenticatedAccountForService =
  513. function flockAccountUtils_getFirstAuthenticatedAccountForService(aServiceContractID)
  514. {
  515.   this._logger.info("{flockIAccountUtils}.getFirstAuthenticatedAccountForService('"+aServiceContractID+"')");
  516.   this.setup();
  517.   var accounts = this._coop.Account.find({serviceId: aServiceContractID, isAuthenticated: true});
  518.   if (accounts.length) {
  519.     return accounts[0].id();
  520.   }
  521.   return null;
  522. }
  523.  
  524. flockAccountUtils.prototype.getPassword =
  525. function flockAccountUtils_getPassword(aKey)
  526. {
  527.   this._logger.info("{flockIAccountUtils}.getPassword('"+aKey+"')");
  528.   var pw = this.getTempPassword(aKey);
  529.   if (!pw) {
  530.     pw = this.getFirstPasswordForHost(aKey);
  531.   }
  532.   return pw;
  533. }
  534.  
  535. flockAccountUtils.prototype.getPasswordForAnyHost =
  536. function flockAccountUtils_getPasswordForAnyHost(aDomain)
  537. {
  538.   this._logger.info("{flockIAccountUtils}.getPasswordForAnyHost('"+aDomain+"')");
  539.   var pm = Components.classes["@mozilla.org/passwordmanager;1"]
  540.                      .getService(Components.interfaces.nsIPasswordManager);
  541.   var en = pm.enumerator;
  542.   while (en.hasMoreElements()) {
  543.     var p = en.getNext();
  544.     p.QueryInterface(Components.interfaces.nsIPassword);
  545.     this._logger.info(" comparing to host: "+p.host);
  546.     if ((p.host == aDomain)
  547.         || (p.host == "http://"+aDomain)
  548.         || (p.host == "https://"+aDomain))
  549.     {
  550.       // found a password for this exact domain
  551.       return p;
  552.     }
  553.     var index = p.host.indexOf("."+aDomain);
  554.     if ((index != -1) && (index + aDomain.length + 1 == p.host.length)) {
  555.       // matched a host in the specified domain
  556.       return p;
  557.     }
  558.   }
  559.   return null;
  560. }
  561.  
  562. flockAccountUtils.prototype.getFirstPasswordForHost =
  563. function flockAccountUtils_getFirstPasswordForHost(aHost)
  564. {
  565.   this._logger.info("{flockIAccountUtils}.getFirstPasswordForHost('"+aHost+"')");
  566.   var pm = Components.classes["@mozilla.org/passwordmanager;1"]
  567.                      .getService(Components.interfaces.nsIPasswordManager);
  568.   var en = pm.enumerator;
  569.   while (en.hasMoreElements()) {
  570.     var p = en.getNext();
  571.     p.QueryInterface(Components.interfaces.nsIPassword);
  572.     if (p.host == aHost) {
  573.       return p;
  574.     }
  575.   }
  576.   return null;
  577. }
  578.  
  579. flockAccountUtils.prototype.getTempPassword =
  580. function flockAccountUtils_getTempPassword(aKey)
  581. {
  582.   this._logger.info("{flockIAccountUtils}.getTempPassword('"+aKey+"')");
  583.   return this.mTempPasswords[aKey];
  584. }
  585.  
  586. flockAccountUtils.prototype.makeTempPasswordPermanent =
  587. function flockAccountUtile_makeTempPasswordPermanent(aKey)
  588. {
  589.   this._logger.info("{flockIAccountUtils}.makeTempPasswordPermanent('"+aKey+"')");
  590.   var temp = this.getTempPassword(aKey);
  591.   if (temp) {
  592.     this.removeAllPasswordsForHost(aKey);
  593.     this.setPassword(aKey, temp.user, temp.password);
  594.     this.clearTempPassword(aKey);
  595.     return this.getPassword(aKey);
  596.   } else {
  597.     this._logger.info(" - ERROR: temporary password does not exist!  Can't make it permanent...");
  598.     // TODO: Maybe throw an exception here?
  599.   }
  600.   return null;
  601. }
  602.  
  603. flockAccountUtils.prototype.markAllAccountsAsLoggedOut =
  604. function flockAccountUtils_markAllAccountsAsLoggedOut(aServiceContractID)
  605. {
  606.   this._logger.info("{flockIAccountUtils}.markAllAccountsAsLoggedOut('"+aServiceContractID+"')");
  607.   this.setup();
  608.   var accounts = this._coop.Account.find({serviceId: aServiceContractID});
  609.   for (var i = 0; i < accounts.length; i++) {
  610.     accounts[i].isAuthenticated = false;
  611.   }
  612. }
  613.  
  614. flockAccountUtils.prototype.setPassword =
  615. function flockAccountUtils_setPassword(aHost, aUser, aPassword)
  616. {
  617.   this._logger.info("{flockIAccountUtils}.setPassword('"+aHost+"', '"+aUser+"', 'XXXXXX')");
  618.   var pm = Components.classes["@mozilla.org/passwordmanager;1"]
  619.                      .getService(Components.interfaces.nsIPasswordManager);
  620.   try {
  621.     pm.addUser(aHost, aUser, aPassword);
  622.   } catch (ex) {
  623.     this._logger.warn("addUser('"+aHost+"', '"+aUser+"') FAILED: "+ex);
  624.   }
  625. }
  626.  
  627. flockAccountUtils.prototype.setTempPassword =
  628. function flockAccountUtils_setTempPassword(aKey, aUser, aPassword, aFormType)
  629. {
  630.   this._logger.info("{flockIAccountUtils}.setTempPassword('"+aKey+"', '"+aUser+"', 'XXXXXXXX', '"+aFormType+"')");
  631.   var pw = {
  632.     QueryInterface: function(aIID) {
  633.       if (!aIID.equals(Components.interfaces.nsISupports) &&
  634.           !aIID.equals(Components.interfaces.nsIPassword) &&
  635.           !aIID.equals(Components.interfaces.flockIPassword)) {
  636.         throw Components.interfaces.NS_ERROR_NO_INTERFACE;
  637.       }
  638.       return this;
  639.     },
  640.     host: aKey,
  641.     user: aUser,
  642.     password: aPassword,
  643.     formType: aFormType
  644.   };
  645.   this.mTempPasswords[aKey] = pw;
  646. }
  647.  
  648. flockAccountUtils.prototype.removeAllPasswordsForHost =
  649. function flockAccountUtils_removeAllPasswordsForHost(aHost)
  650. {
  651.   this._logger.info("{flockIAccountUtils}.removeAllPasswordsForHost('"+aHost+"')");
  652.   var pm = Components.classes["@mozilla.org/passwordmanager;1"]
  653.                      .getService(Components.interfaces.nsIPasswordManager);
  654.   var en = pm.enumerator;
  655.   while (en.hasMoreElements()) {
  656.     var p = en.getNext()
  657.               .QueryInterface(Components.interfaces.nsIPassword);
  658.     if (p.host == aHost) {
  659.       try {
  660.         pm.removeUser(p.host, p.user);
  661.       } catch (ex) {
  662.         this._logger.debug( "ERROR - perhaps an attempt to remove a password "
  663.                           + "that has already been removed... ?");
  664.         this._logger.debug(" host: "+aHost);
  665.       }
  666.     }
  667.   }
  668. }
  669.  
  670. flockAccountUtils.prototype.raiseNotification =
  671. function flockAccountUtils_raiseNotification(aStreamUrn, aNotificationUrn, aNotificationProps)
  672. {
  673.   this._logger.info("{flockIAccountUtils}.raiseNotification('"+aStreamUrn+"', '"+aNotificationUrn+"', aNotificationProps)");
  674.   aNotificationProps.QueryInterface(Components.interfaces.nsIPropertyBag);
  675.   var notification = new this._coop.Notification(aNotificationUrn);
  676.   notification.datevalue = new Date();
  677.   var props = aNotificationProps.enumerator;
  678.   while (props.hasMoreElements()) {
  679.     var prop = props.getNext();
  680.     prop.QueryInterface(Components.interfaces.nsIProperty);
  681.     notification[prop.name] = prop.value;
  682.   }
  683.   var notificationStream = this._coop.get(aStreamUrn);
  684.   notificationStream.children.addOnce(notification);
  685.   // OBS.notifyObservers(this, "new-stuff-notification", notification.id());
  686. }
  687.  
  688. flockAccountUtils.prototype.extractPasswordFromHTMLForm =
  689. function flockAccountUtils_extractPasswordFromHTMLForm(aForm)
  690. {
  691.   this._logger.info("{flockIAccountUtils}.extractPasswordFromHTMLForm(aForm)");
  692.   aForm.QueryInterface(Components.interfaces.nsIDOMHTMLFormElement);
  693.   var formElements = aForm.elements;
  694.   var passElements = [];
  695.   var username = "";
  696.   var firstPasswordIndex = formElements.length;
  697.   for (var i = 0; i < formElements.length; i++) {
  698.     var formElement = formElements.item(i);
  699.     if (formElement.type == "password") {
  700.       passElements.push(formElement);
  701.       if (firstPasswordIndex == formElements.length) {
  702.         firstPasswordIndex = i;
  703.       }
  704.     }
  705.   }
  706.   if (firstPasswordIndex == formElements.length) {
  707.     // We didn't find a password
  708.     return null;
  709.   }
  710.   // Backwards to get closest text field
  711.   for (var i = firstPasswordIndex - 1; i >= 0; i--) {
  712.     var formElement = formElements.item(i);
  713.     if (formElement.type == "text") {
  714.       username = formElement.value;
  715.       break;
  716.     }
  717.   }
  718.   var pwObj = {
  719.     host: "",
  720.     password: passElements[0].value,
  721.     user: username
  722.   };
  723.   return pwObj;
  724. }
  725.  
  726. flockAccountUtils.prototype.decorateDocument =
  727. function flockAccountUtils_decorateDocument(aDocument, aCategory, aName, aValue)
  728. {
  729.   this._logger.info("{flockIAccountUtils}.decorateDocument(aDocument, '"+aCategory+"', '"+aName+"', '"+aValue+"')");
  730.   aDocument.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
  731.   if (!aDocument._flock_decorations) {
  732.     aDocument._flock_decorations = {};
  733.   }
  734.   var fd = aDocument._flock_decorations;
  735.   if (!fd[aCategory]) {
  736.     fd[aCategory] = {};
  737.   }
  738.   fd[aCategory][aName] = aValue;
  739. }
  740.  
  741. flockAccountUtils.prototype.getDocumentDecoration =
  742. function flockAccountUtils_getDocumentDecoration(aDocument, aCategory, aName)
  743. {
  744.   this._logger.info("{flockIAccountUtils}.getDocumentDecoration(aDocument, '"+aCategory+"', '"+aName+"')");
  745.   aDocument.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
  746.   try {
  747.     var value = aDocument._flock_decorations[aCategory][aName];
  748.     return value;
  749.   } catch (ex) {
  750.     return null;
  751.   }
  752. }
  753.  
  754. flockAccountUtils.prototype.useWebDetective =
  755. function flockAccountUtils_useWebDetective(aDetectionFileName)
  756. {
  757.   this._logger.info("{flockIAccountUtils}.useWebDetective('"+aDetectionFileName+"')");
  758.   this.setup();
  759.   var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
  760.                          .getService(Components.interfaces.nsIProperties);
  761.   var profDir = dirSvc.get("ProfD", Components.interfaces.nsIFile);
  762.   var file = Components.classes["@mozilla.org/file/local;1"]
  763.                        .createInstance(Components.interfaces.nsILocalFile);
  764.   file.initWithPath(profDir.path);
  765.   file.append("detect");
  766.   var profDetectDir = file.clone();
  767.   if (!profDetectDir.exists()) {
  768.     profDetectDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
  769.   }
  770.   file.append(aDetectionFileName);
  771.   if (!file.exists()) {
  772.     // The file doesn't exist in the profile, so check if there's one in the
  773.     // res folder that we can copy over
  774.     var resDir = dirSvc.get("ARes", Components.interfaces.nsIFile);
  775.     var file2 = Components.classes["@mozilla.org/file/local;1"]
  776.                           .createInstance(Components.interfaces.nsILocalFile);
  777.     file2.initWithPath(resDir.path);
  778.     file2.append("detect");
  779.     file2.append(aDetectionFileName);
  780.     if (!file2.exists()) {
  781.       this._logger.info("File does not exist: "+aDetectionFileName);
  782.     }
  783.     file2.copyTo(profDetectDir, aDetectionFileName);
  784.     file = profDetectDir.clone();
  785.     file.append(aDetectionFileName);
  786.   }
  787.   var webDetective = Components.classes["@flock.com/web-detective;1"]
  788.                                .getService(Components.interfaces.flockIWebDetective);
  789.   webDetective.loadDetectFile(file);
  790.   return webDetective;
  791. }
  792.  
  793. flockAccountUtils.prototype.removeCookies =
  794. function flockAccountUtils_removeCookies(aCookies)
  795. {
  796.   aCookies.QueryInterface(Components.interfaces.nsISimpleEnumerator);
  797.   var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"]
  798.                                 .getService(Components.interfaces.nsICookieManager);
  799.   var deletedCount = 0;
  800.   while (aCookies.hasMoreElements()) {
  801.     var c = aCookies.getNext()
  802.       .QueryInterface(Components.interfaces.nsICookie);
  803.     cookieManager.remove(c.host, c.name, c.path, false);
  804.     deletedCount++;
  805.   }
  806.   this._logger.info(".removeCookies() - Deleted "+deletedCount+" cookies");
  807. }
  808.  
  809. flockAccountUtils.prototype.isPeopleSidebarOpen =
  810. function flockAccountUtils_isPeopleSidebarOpen()
  811. {
  812.   var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  813.                      .getService(Components.interfaces.nsIWindowMediator);
  814.   var win = wm.getMostRecentWindow("navigator:browser");
  815.   var psbBroadcaster = win.document.getElementById("flockPeopleSidebarBroadcaster");
  816.   if (psbBroadcaster.hasAttribute("checked")) {
  817.     return true;
  818.   } else {
  819.     return false;
  820.   }
  821. }
  822. // END flockIAccountUtils interface
  823.  
  824.  
  825. // BEGIN helper functions
  826. flockAccountUtils.prototype.setup =
  827. function flockAccountUtils_setup()
  828. {
  829.   if (this.mSetupHasRun) {
  830.     return;
  831.   } else {
  832.     this.mSetupHasRun = true;
  833.     this._coop = Components.classes["@flock.com/singleton;1"]
  834.                            .getService(Components.interfaces.flockISingleton)
  835.                            .getSingleton("chrome://flock/content/common/load-faves-coop.js")
  836.                            .wrappedJSObject;
  837.   }
  838. }
  839.  
  840. flockAccountUtils.prototype.getAllAccounts =
  841. function flockAccountUtils_getAllAccounts()
  842. {
  843.   return this._coop.Account.all();
  844. }
  845. // END helper functions
  846.  
  847. // ========== END flockAccountUtils class ==========
  848.  
  849.  
  850.  
  851. // ================================================
  852. // ========== BEGIN XPCOM Module support ==========
  853. // ================================================
  854.  
  855. // BEGIN flockAccountUtilsModule object
  856. var flockAccountUtilsModule = {};
  857.  
  858. flockAccountUtilsModule.registerSelf =
  859. function flockAccountUtilsModule_registerSelf(compMgr, fileSpec, location, type)
  860. {
  861.   compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  862.   compMgr.registerFactoryLocation( ACCOUNTUTILS_CID, 
  863.                                    "Flock Account Utils JS Component",
  864.                                    ACCOUNTUTILS_CONTRACTID, 
  865.                                    fileSpec, 
  866.                                    location,
  867.                                    type );
  868. }
  869.  
  870. flockAccountUtilsModule.getClassObject =
  871. function flockAccountUtilsModule_getClassObject(compMgr, cid, iid)
  872. {
  873.   if (!cid.equals(ACCOUNTUTILS_CID)) {
  874.     throw Components.results.NS_ERROR_NO_INTERFACE;
  875.   }
  876.   if (!iid.equals(Components.interfaces.nsIFactory)) {
  877.     throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
  878.   }
  879.   return flockAccountUtilsFactory;
  880. }
  881.  
  882. flockAccountUtilsModule.canUnload =
  883. function flockAccountUtilsModule_canUnload(compMgr)
  884. {
  885.   return true;
  886. }
  887. // END flockAccountUtilsModule object
  888.  
  889.  
  890. // BEGIN flockAccountUtilsFactory object
  891. var flockAccountUtilsFactory = {};
  892.  
  893. flockAccountUtilsFactory.createInstance =
  894. function flockAccountUtilsFactory_createInstance(outer, iid)
  895. {
  896.   if (outer != null) {
  897.     throw Components.results.NS_ERROR_NO_AGGREGATION;
  898.   }
  899.   return (new flockAccountUtils()).QueryInterface(iid);
  900. }
  901. // END flockAccountUtilsFactory object
  902.  
  903.  
  904. // NS module entry point
  905. function NSGetModule(compMgr, fileSpec) {
  906.   return flockAccountUtilsModule;
  907. }
  908.  
  909. // ========== END XPCOM module support ==========
  910.